home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Games of Daze
/
Infomagic - Games of Daze (Summer 1995) (Disc 1 of 2).iso
/
djgpp
/
go32
/
exphdlr.c
< prev
next >
Wrap
C/C++ Source or Header
|
1994-08-04
|
39KB
|
1,371 lines
/* This is file EXPHDLR.C */
/*
** Copyright (C) 1993 DJ Delorie, 24 Kirsten Ave, Rochester NH 03867-2954
**
** This file is distributed under the terms listed in the document
** "copying.dj", available from DJ Delorie at the address above.
** A copy of "copying.dj" should accompany this file; if not, a copy
** should be available from where this file was obtained. This file
** may not be distributed without a verbatim copy of "copying.dj".
**
** This file is distributed WITHOUT ANY WARRANTY; without even the implied
** warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*/
/* Modified for VCPI Implement by Y.Shibata Aug 5th 1991 */
/* Modified for DPMI Implement by H.Tsubakimoto */
/* Merged DPMI with V1.09+ C. Sandmann sandmann@clio.rice.edu */
/* History:66,55 */
#include <process.h>
#include <stdio.h>
#include <dos.h>
#include <sys/stat.h>
#include <time.h>
#include <errno.h>
#include <fcntl.h>
#include <string.h>
#include <dir.h>
#include <ctype.h>
#include <io.h>
#include "gotypes.h"
#include "gdt.h"
#include "idt.h"
#include "tss.h"
#include "utils.h"
#include "paging.h"
#include "npx.h"
#include "mono.h"
#include "vcpi.h"
#include "graphics.h"
#include "dpmi.h"
#include "extdebug.h"
#include "vcpi.h"
#include "ustat.h"
#include "dpmisim.h"
#include "dalloc.h"
#include "valloc.h"
#include "control.h"
extern void do_faulting_finish_message(int);
extern int old_video_mode;
void segfault(word32 v)
{
if (!using_external_debugger || (tss_ptr == &ed_tss))
{
if (peekb(0x40, 0x49) != old_video_mode)
{
_AX = old_video_mode;
geninterrupt(0x10);
}
fprintf(stderr, "Segmentation violation in pointer 0x%08lx at %x:%lx\n", v-ARENA, tss_ptr->tss_cs, tss_ptr->tss_eip);
do_faulting_finish_message(0);
}
tss_ptr->tss_irqn = 14; /* make it a segfault */
tss_ptr->tss_cr2 = v;
}
#define CHECK_SEGFAULT(p) { \
if (!page_is_valid(p)) \
{ \
segfault(p); \
return 1; \
} \
}
extern int debug_mode;
extern unsigned int cdecl _openfd[];
extern word32 far *graphics_pt;
extern int ctrl_break_hit;
extern int was_user_int;
extern word16 vcpi_installed; /* VCPI Installed flag */
word16 new_pic; /* current IRQ0 Vector */
char transfer_buffer[4096]; /* must be near ptr for small model */
word32 transfer_linear;
int in_hardware_interrupt = 0;
word8 old_master_lo=0x08;
word8 hard_master_lo=0x08, hard_master_hi=0x0f;
word8 hard_slave_lo=0x70, hard_slave_hi=0x77;
word32 user_dta;
static struct REGPACK r;
static int in_graphics_mode=0;
int ctrl_c_causes_break=1;
static int i_10(void), i_21(void), i_31(void), i_33(void), generic_handler(void), i_21_44(void);
static int turbo_assist(void);
static word32 flmerge(word32 rf, word32 tf)
{
return (rf & 0xcff) | (tf & 0xfffff300L);
}
void static set_controller(int v)
{
/* disable(); */
int oldmask = inportb(0x21);
outportb(0x20, 0x11);
outportb(0x21, v);
outportb(0x21, 4);
outportb(0x21, 1);
outportb(0x21, oldmask);
/* enable(); */
}
static char cntrls_initted = 0;
extern char vector_78h, vector_79h;
int find_empty_pic(void)
{
static word8 try[] = { 0x88, 0x90, 0x98, 0xa0, 0xa8, 0xb0, 0xb8, 0xf8, 0x68, 0x78 };
int i, j;
for (i=0; i<sizeof(try); i++)
{
char far * far * vec = (char far * far *)(0L+try[i]*4L);
for (j=1; j<8; j++)
{
if (vec[j] != vec[0])
goto not_empty;
}
/* printf("Empty = %d\n", try[i]); */
return try[i];
not_empty:;
}
return 0x78;
}
extern int far _ev_kbinter; /* keyboard interrupt flag */
extern void interrupt (* far _ev_oldkbint)(void);
extern void interrupt _ev_keybdint(void);
extern void interrupt (* far _ev_oldcriterr)(void);
extern void interrupt _ev_criterr(void);
word32 saved_interrupt_table[256];
void init_controllers(void)
{
if(cntrls_initted) return;
cntrls_initted = 1;
movedata(0, 0, _DS, FP_OFF(saved_interrupt_table), 256*4);
disable();
if (vcpi_installed)
{
old_master_lo = vcpi_get_pic();
hard_slave_lo = vcpi_get_secpic();
/* printf("VCPI pics were m=%d s=%d\n", old_master_lo, hard_slave_lo); */
hard_slave_hi = hard_slave_lo + 7;
}
else if(!use_DPMI)
{
old_master_lo = 0x08;
hard_slave_lo = 0x70;
hard_slave_hi = 0x77;
}
_ev_kbinter = 1;
_ev_oldkbint = getvect(8+1); /* this is *NOT* old_master_lo - required */
setvect(8+1,_ev_keybdint); /* so DV/X will work (it redirects) */
_ev_oldcriterr = getvect(0x24); /* critical error handler can't read kb */
setvect(0x24,_ev_criterr); /* so we force failure if events active */
if(use_DPMI)
{
enable();
return;
}
if (old_master_lo == 0x08)
{
hard_master_lo = find_empty_pic();
if (vcpi_installed)
vcpi_set_pics(hard_master_lo, hard_slave_lo);
set_controller(hard_master_lo);
movedata(0, 0x08*4, 0, hard_master_lo*4, 0x08*4);
}
else
{
hard_master_lo = old_master_lo;
}
hard_master_hi = hard_master_lo + 7;
enable();
vector_78h = hard_master_lo;
vector_79h = hard_master_lo + 1;
}
void uninit_controllers(void)
{
if(!cntrls_initted) return;
cntrls_initted = 0;
disable();
movedata(_DS, FP_OFF(saved_interrupt_table), 0, 0, 256*4);
if (old_master_lo == 0x08 && !use_DPMI)
{
if (vcpi_installed)
vcpi_set_pics(0x08, hard_slave_lo);
set_controller(0x08);
}
setvect(8+1,_ev_oldkbint); /* not old_master_lo for XDV */
enable();
}
static DPMIaddress exceptions[17];
static DPMIaddress interrupt10;
static DPMIaddress interrupt21;
static DPMIaddress interrupt33;
static DPMIaddress interrupt75;
void setDPMIvector(void)
{
int i;
for (i = 0; i < sizeof(exceptions) / sizeof(*exceptions); ++i) {
DPMIehandler(i, &exceptions[i]);
DPMIchangeException(i, &exceptions[i]);
}
DPMIhandler(0x10, &interrupt10);
DPMIchangeInterrupt(0x10, &interrupt10);
DPMIhandler(0x21, &interrupt21);
DPMIchangeInterrupt(0x21, &interrupt21);
DPMIhandler(0x33, &interrupt33);
DPMIchangeInterrupt(0x33, &interrupt33);
DPMIhandlerNPX(&interrupt75);
DPMIchangeInterrupt(0x75, &interrupt75);
}
void restoreDPMIvector(void)
{
int i;
for (i = 0; i < sizeof(exceptions) / sizeof(*exceptions); ++i)
DPMIchangeException(i, &exceptions[i]);
DPMIchangeInterrupt(0x10, &interrupt10);
DPMIchangeInterrupt(0x21, &interrupt21);
DPMIchangeInterrupt(0x33, &interrupt33);
DPMIchangeInterrupt(0x75, &interrupt75);
}
void tss2reg(struct REGPACK *r)
{
r->r_ax = (word16)(tss_ptr->tss_eax);
r->r_bx = (word16)(tss_ptr->tss_ebx);
r->r_cx = (word16)(tss_ptr->tss_ecx);
r->r_dx = (word16)(tss_ptr->tss_edx);
r->r_si = (word16)(tss_ptr->tss_esi);
r->r_di = (word16)(tss_ptr->tss_edi);
r->r_flags = (word16)(tss_ptr->tss_eflags);
r->r_ds = r->r_es = _DS;
}
void reg2tss(struct REGPACK *r)
{
tss_ptr->tss_eax = r->r_ax;
tss_ptr->tss_ebx = r->r_bx;
tss_ptr->tss_ecx = r->r_cx;
tss_ptr->tss_edx = r->r_dx;
tss_ptr->tss_esi = r->r_si;
tss_ptr->tss_edi = r->r_di;
tss_ptr->tss_eflags = flmerge(r->r_flags, tss_ptr->tss_eflags);
}
/* The following routine should be used for _unsupported_ interrupt reflection
* to real mode for go32. For any inrerrupts not directly handled by go32,
* the return registers should _not_ be signed extended to fit the 32 bit
* extended registers, but should ensure that the high order words are
* preserved across the interrupt (this is how other extenders like DOS/4GW
* and X32-VM do it). If you are calling the interrupt from int86() this is
* not a problem, but if you do it from assembly code then it is ;-)
*/
void reg2tss_short(struct REGPACK *r)
{
(short)tss_ptr->tss_eax = r->r_ax;
(short)tss_ptr->tss_ebx = r->r_bx;
(short)tss_ptr->tss_ecx = r->r_cx;
(short)tss_ptr->tss_edx = r->r_dx;
(short)tss_ptr->tss_esi = r->r_si;
(short)tss_ptr->tss_edi = r->r_di;
tss_ptr->tss_eflags = flmerge(r->r_flags, tss_ptr->tss_eflags);
}
extern int ctrl_c_flag;
int double_fault(void)
{
fprintf(stderr, "double fault!\n");
exit(1);
return 1;
}
int check_nonpresent_387(void )
{
if (!using_external_debugger)
{
fprintf(stderr, "Fatal! Application attempted to use not-present 80387!\n");
fprintf(stderr, "Floating point opcode at virtual address 0x%08lx\n", tss_ptr->tss_eip);
}
return 1;
}
int unsupported_int()
{
if (!debug_mode)
fprintf(stderr, "Unsupported INT 0x%02x\n", tss_ptr->tss_irqn);
return 1;
}
#define U unsupported_int
typedef int (*FUNC)(void);
static FUNC exception_handler_list[] = {
U, U, U, U, U, U, U,
/* 07 */ check_nonpresent_387,
/* 08 */ double_fault,
U, U, U, U, U,
/* 0e */ page_in,
U,
/* 10 */ i_10, /* Video Interrupt */
/* 11 */ generic_handler, /* Equipment detection */
/* 12 */ generic_handler, /* Get memory size (outdated) */
U,
/* 14 */ generic_handler, /* Serial communication */
/* 15 */ generic_handler, /* Lots of strange things */
/* 16 */ generic_handler, /* Keyboard */
/* 17 */ generic_handler, /* Parallel printer */
U, U,
/* 1a */ generic_handler, /* Get/set system time */
U, U, U, U, U, U,
/* 21 */ i_21, /* DOS Services */
U, U, U, U, U, U, U, U, U, U, U, U, U, U, U,
/* 31 */ i_31, /* DPMIsim */
U,
/* 33 */ i_33 /* Mouse */
};
#undef U
#define NUM_EXCEPTIONS (sizeof(exception_handler_list)/sizeof(exception_handler_list[0]))
exception_handler(void)
{
int i;
if (topline_info)
{
char buf[20];
if (tss_ptr->tss_irqn == 14)
sprintf(buf, "0x%08lx", tss_ptr->tss_cr2 - ARENA);
else
sprintf(buf, "0x%08lx", tss_ptr->tss_eip);
for (i=0; buf[i]; i++)
poke(screen_seg, i*2+80, buf[i] | 0x0600);
}
i = tss_ptr->tss_irqn;
/* printf("i=%#02x\n", i); */
if (((i >= hard_slave_lo) && (i <= hard_slave_hi)
&& (i != hard_slave_lo + 5))
|| ((i >= hard_master_lo) && (i <= hard_master_hi)))
{
in_hardware_interrupt = 1;
intr(i, &r);
in_hardware_interrupt = 0;
if (ctrl_break_hit)
return 1;
if (i == hard_master_lo + 1)
{
if (ctrl_c_causes_break)
{
r.r_ax = 0x0100;
intr(0x16, &r);
if (!(r.r_flags & 0x40) && (r.r_ax == 0x2e03))
{
_AH = 0;
geninterrupt(0x16);
ctrl_c_flag = 1;
}
}
}
if (ctrl_c_flag)
{
ctrl_c_flag = 0;
if (ctrl_c_causes_break)
return 1;
}
return 0;
}
if (i < NUM_EXCEPTIONS)
return (exception_handler_list[i])();
else
return 1;
}
void retrieve_string(word32 v, char *transfer_buffer, char tchar)
{
int i;
if (!use_DPMI) {
#if 0
for (i=0; i<4096; i++)
{
c = peek8(v);
v++;
transfer_buffer[i] = c;
if (c == tchar)
break;
}
#else
memscan32(v, transfer_buffer, tchar);
#endif
return;
} else {
i = Pmemscan(tss_ptr->tss_ds, v, tchar, 4096);
if (i == 0) i = 4096;
Pmemget(tss_ptr->tss_ds, v, transfer_buffer, i);
return;
}
}
generic_handler(void)
{
tss2reg(&r);
intr(tss_ptr->tss_irqn, &r);
reg2tss_short(&r); /* KJB */
return 0;
}
i_10(void)
{
word32 v;
word16 i, j;
/* CB changes */
/* OLD:
* switch((word16)(tss_ptr->tss_eax) & 0xFF00) {
* case 0xFD00:
* graphics_pageflip();
* return 0;
* case 0xFE00:
* graphics_inquiry();
* return 0;
* case 0xFF00:
* graphics_mode((word16)(tss_ptr->tss_eax) & 0xff);
* in_graphics_mode = (peekb(0x40, 0x49) > 7);
* return 0;
* }
*/
if(((word16)tss_ptr->tss_eax & 0xff00) >= gr_assist_func_start) {
graphics_assist();
in_graphics_mode = (peekb(0x40, 0x49) > 7);
return 0;
}
/* end CB changes */
tss2reg(&r);
i = (word16)tss_ptr->tss_eax; /* int10 function 0x11 subfunctions 0 & 0x10 */
if(i==0x1100 || i==0x1110)
{ /* user-defined text characters */
v = tss_ptr->tss_edx + ARENA; /* bh*cx bytes starting at (ds:dx) */
CHECK_SEGFAULT(v);
j = ((tss_ptr->tss_ebx >> 8) & 0xff) * ((word16)tss_ptr->tss_ecx);
memget(v, transfer_buffer, j);
r.r_dx = FP_OFF(transfer_buffer);
r.r_ds = _DS;
intr(0x10, &r);
reg2tss(&r);
tss_ptr->tss_ebp = r.r_es * 16L + r.r_bp + 0xe0000000L;
return 0;
}
/* KJB - All unknown interrupts fall through to here (VESA VBE interrupts are
* one set) and we use the reg2tss_short() routine to copy the registers
* without sign extension so that we dont trash registers that the
* application is not expecting to be changed. Note also that I moved the
* code to change EBP into the above routine where it belongs.
*/
intr(0x10, &r);
reg2tss_short(&r);
if (i == 0x1130)
tss_ptr->tss_ebp = r.r_es * 16L + r.r_bp + 0xe0000000L;
return 0;
}
#include "eventque.h"
#define MSDRAW_STACK 128 /* stack size for mouse callback */
static word32 mousedraw_func32; /* 32-bit mouse cursor drawing function */
static word32 mousedraw_contaddr; /* jump to this address after mouse draw */
static char mousedraw_active; /* set while drawing mouse cursor */
EventQueue *event_queue = NULL; /* event queue */
typedef int far (*FFUNC)(void);
static FFUNC mousedraw_callback = 0; /* DPMI real mode callback to prot */
static void mousedraw_hook(void)
{
disable();
if(!mousedraw_active)
{
mousedraw_active = 1;
if(use_DPMI)
{
mousedraw_callback();
mousedraw_active = 0;
}
else
{
mousedraw_contaddr = a_tss.tss_eip;
a_tss.tss_eip = mousedraw_func32;
}
}
enable();
}
i_33(void)
{
void (*msdrawfun)(void);
int queuesize;
if(tss_ptr->tss_eax == 0x00ff) {
if(event_queue != NULL) {
EventQueueDeInit();
event_queue = NULL;
}
if((queuesize = (int)tss_ptr->tss_ebx) > 0) {
mousedraw_func32 = tss_ptr->tss_ecx;
mousedraw_active = 0;
msdrawfun = (mousedraw_func32 != 0L) ? mousedraw_hook : NULL;
if(use_DPMI) {
if(tss_ptr->tss_edx != 0x12345678L) return(0); /* make sure V1.03 or more */
mousedraw_callback = (FFUNC)mousedraw_func32;
}
event_queue = EventQueueInit(queuesize, MSDRAW_STACK, msdrawfun);
if(event_queue != NULL) {
tss_ptr->tss_ebx =
(((word32)FP_SEG(event_queue)) << 4) +
((word32)FP_OFF(event_queue)) +
0xe0000000L;
tss_ptr->tss_ecx =
(((word32)FP_SEG(&mousedraw_contaddr)) << 4) +
((word32)FP_OFF(&mousedraw_contaddr)) +
0xe0000000L;
tss_ptr->tss_edx =
(((word32)FP_SEG(&mousedraw_active)) << 4) +
((word32)FP_OFF(&mousedraw_active)) +
0xe0000000L;
}
else tss_ptr->tss_ebx = 0L;
}
tss_ptr->tss_eax = 0x0ff0; /* acknowledge event handling */
return(0);
}
if (*((unsigned far *)0x000000CEL) == 0)
return 0;
r.r_ax = (word16)(tss_ptr->tss_eax);
r.r_bx = (word16)(tss_ptr->tss_ebx);
r.r_cx = (word16)(tss_ptr->tss_ecx);
r.r_dx = (word16)(tss_ptr->tss_edx);
intr(0x33, &r);
tss_ptr->tss_eax = r.r_ax;
tss_ptr->tss_ebx = r.r_bx;
tss_ptr->tss_ecx = r.r_cx;
tss_ptr->tss_edx = r.r_dx;
return 0;
}
/*1.07 TSS last_tss; */
i_21(void)
{
word32 v, trans_total, countleft;
int i, c, ah, tchar, trans_count;
char *cp;
tss2reg(&r);
ah = ((word16)(tss_ptr->tss_eax) >> 8) & 0xff;
if (ah & 0x80) switch (ah)
{
case 0xfe:
return external_debugger_handler();
case 0xff:
return turbo_assist();
default:
return 1;
}
else switch (ah)
{
case 0x42: /* seek */
_openfd[r.r_bx] &= 0xfdff; /* clear EOF */
/* fall through */
case 0x01: /* read with echo */
case 0x02: /* con output */
case 0x03: /* aux input */
case 0x04: /* aux output */
case 0x05: /* prn output */
case 0x06: /* direct con i/o */
case 0x07: /* direct con input */
case 0x08: /* kbd read */
case 0x0b: /* kbd status */
case 0x0d: /* reset disk */
case 0x0e: /* select disk */
case 0x18: /* return al=0 */
case 0x19: /* get disk */
case 0x1d: /* return al=0 */
case 0x1e: /* return al=0 */
case 0x20: /* return al=0 */
case 0x2a: /* get date */
case 0x2b: /* set date */
case 0x2c: /* get time */
case 0x2d: /* set time */
case 0x2e: /* (re)set verify flag */
case 0x30: /* get version */
case 0x36: /* get disk free space */
case 0x37: /* get/set switch char */
case 0x4d: /* get return code */
case 0x54: /* get verify flag */
case 0x57: /* get/set file time stamp */
case 0x58: /* get/set UMB link state */
case 0x5c: /* file locking */
case 0x66: /* get/set global code page */
case 0x67: /* set handle count */
case 0x68: /* commit (flush and update directory) */
intr(0x21, &r);
reg2tss(&r);
return 0;
case 0x38: /* get country info */
r.r_ds = _DS;
r.r_dx = FP_OFF(transfer_buffer);
intr(0x21, &r);
if (r.r_flags & 1)
{
tss_ptr->tss_eflags |= 1;
tss_ptr->tss_eax = r.r_ax;
return 0;
}
memput(tss_ptr->tss_edx + ARENA, transfer_buffer, 34);
return 0;
case 0x33: /* ^C checking and more */
switch (r.r_ax & 0xff)
{
case 0x01: /* set ^C */
case 0x02: /* set extended ^C */
ctrl_c_causes_break = r.r_dx & 0xff;
/* fall through */
case 0x00: /* get ^C */
case 0x05: /* get boot drive */
case 0x06: /* get true dos version */
intr(0x21, &r);
reg2tss(&r);
return 0;
default:
return 1;
}
case 0x3e: /* close */
if (using_external_debugger && r.r_bx < 2)
return 0;
if (r.r_bx == 1)
redir_1_mono = 0;
if (r.r_bx == 2)
redir_2_mono = 0;
intr(0x21, &r);
reg2tss(&r);
return 0;
case 9: /* print string */
case 0x39: /* mkdir */
case 0x3a: /* rmdir */
case 0x3b: /* chdir */
case 0x41: /* unlink (delete) */
case 0x43: /* chmod */
if (ah == 9)
tchar = '$';
else
tchar = 0;
v = tss_ptr->tss_edx + ARENA;
CHECK_SEGFAULT(v);
retrieve_string(v, transfer_buffer, tchar);
r.r_dx = FP_OFF(transfer_buffer);
r.r_ds = _DS;
intr(0x21, &r);
reg2tss(&r);
return 0;
case 0x3c: /* creat (rewrite) */
v = tss_ptr->tss_edx + ARENA;
CHECK_SEGFAULT(v);
retrieve_string(v, transfer_buffer, 0);
i = _creat(transfer_buffer, (int)(tss_ptr->tss_ecx));
if (i < 0)
{
tss_ptr->tss_eax = errno;
tss_ptr->tss_eflags |= 1;
}
else
{
tss_ptr->tss_eax = i;
tss_ptr->tss_eflags &= ~1;
}
return 0;
case 0x3d: /* open */
v = tss_ptr->tss_edx + ARENA;
CHECK_SEGFAULT(v)
retrieve_string(v, transfer_buffer, 0);
i = (word16)(tss_ptr->tss_eax) & 0xf0;
if (tss_ptr->tss_eax & O_WRONLY) i |= 1;
if (tss_ptr->tss_eax & O_RDWR) i |= 2;
i = _open(transfer_buffer, i);
if (i < 0)
{
tss_ptr->tss_eax = errno;
tss_ptr->tss_eflags |= 1;
}
else
{
tss_ptr->tss_eax = i;
tss_ptr->tss_eflags &= ~1;
}
return 0;
case 0x1a: /* set dta */
user_dta = tss_ptr->tss_edx;
setdta((char far *)transfer_buffer);
return 0;
case 0x2f: /* get dta */
tss_ptr->tss_ebx = user_dta;
return 0;
case 0x56: /* rename/move */
v = tss_ptr->tss_edx + ARENA;
CHECK_SEGFAULT(v)
retrieve_string(v, transfer_buffer, 0);
i = strlen(transfer_buffer) + 1;
r.r_dx = FP_OFF(transfer_buffer);
r.r_ds = _DS;
v = tss_ptr->tss_edi + ARENA;
retrieve_string(v, transfer_buffer+i, 0);
r.r_di = FP_OFF(transfer_buffer)+i;
r.r_es = _DS;
intr(0x21, &r);
tss_ptr->tss_eax = r.r_ax;
tss_ptr->tss_eflags = flmerge(r.r_flags, tss_ptr->tss_eflags);
return 0;
case 0x3f: /* read */
if (!tss_ptr->tss_edx) {
fprintf(stderr, "This image has a buggy read.s module. Run DPMIFIX on it and try again.\n");
return 1;
}
if (tss_ptr->tss_edx == transfer_linear)
{
i = read(r.r_bx, transfer_buffer, r.r_cx);
if (i<0)
{
tss_ptr->tss_eflags |= 1; /* carry */
tss_ptr->tss_eax = _doserrno;
}
else
{
tss_ptr->tss_eflags &= ~1;
tss_ptr->tss_eax = i;
}
return 0;
}
trans_total = 0;
countleft = tss_ptr->tss_ecx;
v = tss_ptr->tss_edx;
CHECK_SEGFAULT(v+ARENA)
while (countleft > 0)
{
trans_count = (word16)((countleft <= 4096) ? countleft : 4096);
i = read(r.r_bx, transfer_buffer, trans_count);
if (i < 0)
{
tss_ptr->tss_eflags |= 1; /* carry */
tss_ptr->tss_eax = _doserrno;
return 0;
}
memput(v+ARENA, transfer_buffer, i);
trans_total += i;
v += i;
countleft -= i;
if (isatty(r.r_bx) && (i<trans_count))
break; /* they're line buffered */
if (i == 0)
break;
}
tss_ptr->tss_eax = trans_total;
tss_ptr->tss_eflags &= ~1;
return 0;
case 0x40: /* write */
if (tss_ptr->tss_edx == transfer_linear)
{
if ((r.r_bx == 1) && redir_1_mono)
i = mono_write(transfer_buffer, r.r_cx);
else if ((r.r_bx == 2) && redir_2_mono)
i = mono_write(transfer_buffer, r.r_cx);
else
{
int fd = r.r_bx;
if (r.r_cx == 0) /* for ftruncate */
i = _write(fd, transfer_buffer, r.r_cx);
else
i = write(fd, transfer_buffer, r.r_cx);
}
if (i<0)
{
tss_ptr->tss_eflags |= 1; /* carry */
tss_ptr->tss_eax = _doserrno;
}
else
{
tss_ptr->tss_eflags &= ~1;
tss_ptr->tss_eax = i;
}
return 0;
}
trans_total = 0;
countleft = tss_ptr->tss_ecx;
if (countleft == 0)
{
r.r_ax = 0x4000;
r.r_cx = 0;
intr(0x21,&r);
tss_ptr->tss_eax = 0;
tss_ptr->tss_eflags &= ~1;
return 0;
}
v = tss_ptr->tss_edx;
CHECK_SEGFAULT(v+ARENA);
r.r_dx = (int)transfer_buffer;
while (countleft > 0)
{
trans_count = (word16)((countleft <= 4096) ? countleft : 4096);
memget(v+ARENA, transfer_buffer, trans_count);
if ((r.r_bx == 1) && redir_1_mono)
i = mono_write(transfer_buffer, trans_count);
else if ((r.r_bx == 2) && redir_2_mono)
i = mono_write(transfer_buffer, trans_count);
else
{
int fd = r.r_bx;
i = write(fd, transfer_buffer, trans_count);
if (in_graphics_mode && (fd < 3))
{
word32 far *p = graphics_pt;
for (c = 0; c < 256; c++)
*p++ &= ~PT_P;
}
}
if (i<0) /* carry */
{
tss_ptr->tss_eflags |= 1; /* carry */
tss_ptr->tss_eax = _doserrno;
return 0;
}
trans_total += i;
v += i;
countleft -= i;
if (i < trans_count)
break;
}
tss_ptr->tss_eax = trans_total;
tss_ptr->tss_eflags &= ~1;
return 0;
case 0x44: /* ioctl */
return i_21_44();
case 0x45: /* dup */
i = _openfd[r.r_bx];
intr(0x21, &r);
if (!(r.r_flags & 1))
_openfd[r.r_ax] = i;
reg2tss(&r);
return 0;
case 0x46: /* dup2 */
i = _openfd[r.r_bx];
c = r.r_cx;
intr(0x21, &r);
if (!(r.r_flags & 1))
_openfd[c] = i;
reg2tss(&r);
return 0;
case 0x4e: /* find first */
CHECK_SEGFAULT(user_dta+ARENA);
v = tss_ptr->tss_edx + ARENA;
CHECK_SEGFAULT(v);
retrieve_string(v, transfer_buffer+43, 0);
r.r_dx = FP_OFF(transfer_buffer+43);
r.r_ds = _DS;
intr(0x21, &r);
reg2tss(&r);
for (i=20; i>=0; i--)
transfer_buffer[i+28] = transfer_buffer[i+26];
transfer_buffer[32+13] = 0; /* asciiz termination */
memput(user_dta+ARENA, transfer_buffer, 48);
return 0;
case 0x4f: /* find next */
CHECK_SEGFAULT(user_dta+ARENA);
memget(user_dta+ARENA, transfer_buffer, 48);
for (i=0; i<=20; i++)
transfer_buffer[i+26] = transfer_buffer[i+28];
intr(0x21, &r);
reg2tss(&r);
for (i=20; i>=0; i--)
transfer_buffer[i+28] = transfer_buffer[i+26];
transfer_buffer[32+13] = 0; /* asciiz termination */
memput(user_dta+ARENA, transfer_buffer, 48);
return 0;
case 0x47: /* getwd */
getcurdir((int)(tss_ptr->tss_edx & 0xff), transfer_buffer);
for (cp=transfer_buffer; *cp; cp++)
{
if (*cp == '\\') *cp = '/';
*cp = tolower(*cp);
}
memput(tss_ptr->tss_esi+ARENA, transfer_buffer, strlen(transfer_buffer)+1);
tss_ptr->tss_eax = (unsigned)r.r_ax;
tss_ptr->tss_eflags &= ~1;
return 0;
case 0x4a: /* sbrk/brk -- NOT ORGINAL MEANING */
if (tss_ptr->tss_eax & 0xff)
tss_ptr->tss_eax = paging_sbrk(tss_ptr->tss_ebx);
else
tss_ptr->tss_eax = paging_brk(tss_ptr->tss_ebx);
return 0;
case 0x4c: /* exit */
if (using_external_debugger && (tss_ptr == &a_tss))
return 1;
else
exit((word8)(tss_ptr->tss_eax));
default:
return 1;
}
}
static int reg2gate(word32 r)
{
int g = (int)(r & 0xff);
if (g >= 0x08 && g <= 0x0f)
g = g - 0x08 + hard_master_lo;
else if (g >= 0x70 && g <= 0x77)
g = g - 0x70 + hard_slave_lo;
return g;
}
static int dpmisim_is_exec = 0;
int i_31(void)
{
int gate, i;
word16 far *fptr;
word16 dpmisim_spare_stack[128];
union REGS r;
struct SREGS s;
switch ((word16)(tss_ptr->tss_eax))
{
case 0x0100:
r.h.ah = 0x48;
r.x.bx = (word16)tss_ptr->tss_ebx;
int86(0x21, &r, &r);
if ((r.x.flags & 1) && ((word16)tss_ptr->tss_ebx != 0xffff))
{
valloc_shrink_rmem(((word16)tss_ptr->tss_ebx)/256 + 1);
r.h.ah = 0x48;
r.x.bx = (word16)tss_ptr->tss_ebx;
int86(0x21, &r, &r);
/* if (r.x.flags & 1)
printf("biggest after shrinking is %04x\n", r.x.bx); */
}
tss_ptr->tss_eflags &= ~1;
tss_ptr->tss_eflags |= r.x.flags & 1;
tss_ptr->tss_edx =
tss_ptr->tss_eax = r.x.ax;
tss_ptr->tss_ebx = r.x.bx;
/* printf("allocated %x, %d %x\n", r.x.ax, r.x.flags & 1, r.x.bx); */
return 0;
case 0x0101:
r.h.ah = 0x49;
s.es = (word16)tss_ptr->tss_edx;
int86x(0x21, &r, &r, &s);
/* printf("released %x, %d %x\n", (word16)tss_ptr->tss_edx, r.x.flags & 1, r.x.ax); */
return 0;
case 0x0102:
r.h.ah = 0x4a;
r.x.bx = (word16)tss_ptr->tss_ebx;
s.es = (word16)tss_ptr->tss_edx;
int86x(0x21, &r, &r, &s);
tss_ptr->tss_eflags &= ~1;
tss_ptr->tss_eflags |= r.x.flags & 1;
tss_ptr->tss_eax = r.x.ax;
tss_ptr->tss_ebx = r.x.bx;
return 0;
case 0x0200:
/* gate = (word8)tss_ptr->tss_ebx; */
gate = reg2gate(tss_ptr->tss_ebx);
tss_ptr->tss_ecx = peek(0, gate*4+2);
tss_ptr->tss_edx = peek(0, gate*4);
tss_ptr->tss_eflags &= ~1;
return 0;
case 0x0201:
/* gate = (word8)tss_ptr->tss_ebx; */
gate = reg2gate(tss_ptr->tss_ebx);
disable();
poke(0, gate*4+2, tss_ptr->tss_ecx);
poke(0, gate*4, tss_ptr->tss_edx);
enable();
tss_ptr->tss_eflags &= ~1;
return 0;
case 0x0204:
gate = reg2gate(tss_ptr->tss_ebx);
tss_ptr->tss_ecx = idt[gate].selector;
tss_ptr->tss_edx = idt[gate].offset0 | (idt[gate].offset1 << 16);
tss_ptr->tss_eflags &= ~1;
return 0;
case 0x0205:
gate = reg2gate(tss_ptr->tss_ebx);
idt[gate].selector = (word16)(tss_ptr->tss_ecx);
idt[gate].offset0 = (word16)(tss_ptr->tss_edx);
idt[gate].offset1 = (word16)(tss_ptr->tss_edx >> 16);
idt[gate].stype = 0x8e00;
tss_ptr->tss_eflags &= ~1;
return 0;
case 0x0300:
case 0x0301:
case 0x0302:
CHECK_SEGFAULT(tss_ptr->tss_edi + ARENA);
if ((word16)tss_ptr->tss_ecx)
{
tss_ptr->tss_eax = 0x8021;
tss_ptr->tss_eflags |= 1;
return 0;
}
memget(tss_ptr->tss_edi + ARENA, dpmisim_regs, 50);
if (dpmisim_regs[24] == 0)
{
dpmisim_regs[24] = _SS;
dpmisim_regs[23] = (word16)(dpmisim_spare_stack) + sizeof(dpmisim_spare_stack);
}
if ((word16)tss_ptr->tss_eax != 0x0301)
{
dpmisim_regs[23] -= 2; /* fake pushing flags on stack */
fptr = MK_FP(dpmisim_regs[24], dpmisim_regs[23]);
*fptr = dpmisim_regs[16];
}
if ((word16)tss_ptr->tss_eax == 0x0300)
{
dpmisim_regs[21] = peek(0, (word8)tss_ptr->tss_ebx * 4);
dpmisim_regs[22] = peek(0, (word8)tss_ptr->tss_ebx * 4 + 2);
}
if (dpmisim_is_exec)
{
word32 our_interrupt_table[256];
page_out_everything();
movedata(0, 0, FP_SEG(our_interrupt_table), FP_OFF(our_interrupt_table), 256*4);
uninit_controllers();
dpmisim();
init_controllers();
ctrl_break_hit = 0;
disable();
movedata(FP_SEG(our_interrupt_table), FP_OFF(our_interrupt_table), 0, 0, 256*4);
enable();
page_in_everything();
}
else
dpmisim();
memput(tss_ptr->tss_edi + ARENA, dpmisim_regs, 50);
tss_ptr->tss_eflags &= ~1;
return 0;
case 0x0303:
CHECK_SEGFAULT(tss_ptr->tss_edi + ARENA);
for (i=0; i<16; i++)
if (dpmisim_rmcb[i].cb_address == 0)
break;
if (i == 16)
{
tss_ptr->tss_eflags |= 1;
tss_ptr->tss_eax = 0x8015;
return 0;
}
dpmisim_rmcb[i].cb_address = tss_ptr->tss_esi;
dpmisim_rmcb[i].reg_ptr = tss_ptr->tss_edi;
tss_ptr->tss_eflags &= ~1;
tss_ptr->tss_ecx = _CS;
tss_ptr->tss_edx = (word16)dpmisim_rmcb0 + i * ((word16)dpmisim_rmcb1 - (word16)dpmisim_rmcb0);
return 0;
case 0x0304:
if ((word16)tss_ptr->tss_ecx == _CS)
for (i=0; i<16; i++)
if ((word16)tss_ptr->tss_edx == (word16)dpmisim_rmcb0 + i * ((word16)dpmisim_rmcb1 - (word16)dpmisim_rmcb0))
{
dpmisim_rmcb[i].cb_address = 0;
tss_ptr->tss_eflags &= ~1;
return 0;
}
tss_ptr->tss_eflags |= 1;
tss_ptr->tss_eax = 0x8024;
return 0;
case 0x0500:
CHECK_SEGFAULT(tss_ptr->tss_edi + ARENA);
memset(transfer_buffer, 0xff, 48);
((word32 *)transfer_buffer)[8] = dalloc_max_size();
((word32 *)transfer_buffer)[4] =
((word32 *)transfer_buffer)[6] = valloc_max_size();
((word32 *)transfer_buffer)[2] =
((word32 *)transfer_buffer)[5] = valloc_max_size() - valloc_used();
((word32 *)transfer_buffer)[1] =
((word32 *)transfer_buffer)[5] + ((word32 *)transfer_buffer)[8] - dalloc_used();
((word32 *)transfer_buffer)[0] = ((word32 *)transfer_buffer)[1] * 4096L;
memput(tss_ptr->tss_edi + ARENA, transfer_buffer, 48);
tss_ptr->tss_eflags &= ~1;
return 0;
case 0x0600: /* These all deal with locking memory. We ignore them for now, */
case 0x0601: /* but allow them to succeed to that in real DPMI mode you can */
case 0x0602: /* use them. */
case 0x0603:
case 0x0702:
case 0x0703:
tss_ptr->tss_eflags &= ~1;
return 0;
case 0x0604:
tss_ptr->tss_ebx = 0;
tss_ptr->tss_ecx = 4096;
tss_ptr->tss_eflags &= ~1;
return 0;
default: /* mark as unsupported */
tss_ptr->tss_eflags |= 1;
tss_ptr->tss_eax = 0x8001;
return 0;
}
}
struct time32 {
word32 secs;
word32 usecs;
};
struct tz32 {
word32 offset;
word32 dst;
};
struct stat32 {
short st_dev;
short st_ino;
short st_mode;
short st_nlink;
short st_uid;
short st_gid;
short st_rdev;
short st_align_for_word32;
long st_size;
long st_atime;
long st_mtime;
long st_ctime;
long st_blksize;
};
turbo_assist(void)
{
word32 p1, p2, r;
struct time32 time32;
struct tz32 tz32;
struct stat32 statbuf32;
struct stat statbuf;
int i;
char buf[128], *bp;
word32 our_interrupt_table[256];
p1 = tss_ptr->tss_ebx;
p2 = tss_ptr->tss_ecx;
switch ((word8)(tss_ptr->tss_eax))
{
case 1: /* creat */
retrieve_string(p1+ARENA, buf, 0);
r = creat(buf, S_IREAD | S_IWRITE);
break;
case 2: /* open */
retrieve_string(p1+ARENA, buf, 0);
r = open(buf, (int)p2, S_IREAD | S_IWRITE);
break;
case 3: /* fstat */
memset(&statbuf, 0, sizeof(statbuf));
r = fstat((int)p1, &statbuf);
statbuf32.st_dev = statbuf.st_dev;
statbuf32.st_ino = statbuf.st_ino;
statbuf32.st_mode = statbuf.st_mode;
statbuf32.st_nlink = statbuf.st_nlink;
statbuf32.st_uid = 42;
statbuf32.st_gid = 42;
statbuf32.st_rdev = statbuf.st_rdev;
statbuf32.st_size = statbuf.st_size;
statbuf32.st_atime = statbuf.st_atime;
statbuf32.st_mtime = statbuf.st_mtime;
statbuf32.st_ctime = statbuf.st_ctime;
statbuf32.st_blksize = 4096;
memput(p2+ARENA, &statbuf32, sizeof(statbuf32));
break;
case 4: /* gettimeofday */
if (p2)
{
CHECK_SEGFAULT(p2+ARENA);
tz32.offset = timezone;
tz32.dst = daylight;
memput(p2+ARENA, &tz32, sizeof(tz32));
}
if (p1)
{
int dh;
CHECK_SEGFAULT(p1+ARENA);
time((long *)&(time32.secs));
_AH = 0x2c;
geninterrupt(0x21);
dh = _DH;
time32.usecs = _DL * 10000L;
if (time32.secs % 60 != dh)
time32.secs++;
memput(p1+ARENA, &time32, sizeof(time32));
}
r = 0;
break;
case 5: /* settimeofday */
if (p2)
{
CHECK_SEGFAULT(p2+ARENA);
memget(p2+ARENA, &tz32, sizeof(tz32));
timezone = tz32.offset;
daylight = (int)tz32.dst;
}
if (p1)
{
CHECK_SEGFAULT(p1+ARENA);
memget(p1+ARENA, &time32, sizeof(time32));
stime((long *)&(time32.secs));
}
r = 0;
break;
case 6: /* stat */
memset(&statbuf, 0, sizeof(statbuf));
retrieve_string(p1+ARENA, transfer_buffer, 0);
r = unixlike_stat(transfer_buffer, &statbuf);
statbuf32.st_dev = statbuf.st_dev;
statbuf32.st_ino = statbuf.st_ino;
statbuf32.st_mode = statbuf.st_mode;
statbuf32.st_nlink = statbuf.st_nlink;
statbuf32.st_uid = statbuf.st_uid;
statbuf32.st_gid = statbuf.st_gid;
statbuf32.st_rdev = statbuf.st_rdev;
statbuf32.st_size = statbuf.st_size;
statbuf32.st_atime = statbuf.st_atime;
statbuf32.st_mtime = statbuf.st_mtime;
statbuf32.st_ctime = statbuf.st_ctime;
statbuf32.st_blksize = 4096;
memput(p2+ARENA, &statbuf32, sizeof(statbuf32));
break;
case 7: /* system */
retrieve_string(p1+ARENA, transfer_buffer, 0);
page_out_everything();
movedata(0, 0, FP_SEG(our_interrupt_table), FP_OFF(our_interrupt_table), 256*4);
uninit_controllers();
sscanf(transfer_buffer, "%s%n", buf, &i);
if (strpbrk(transfer_buffer, "<>|") == NULL)
r = spawnlp(P_WAIT, buf, buf, transfer_buffer+i, 0);
else
r = -1;
bp = buf+strlen(buf)-4;
if (stricmp(bp, ".exe") && stricmp(bp, ".com") && (r & 0x80000000L))
r = system(transfer_buffer);
init_controllers();
ctrl_break_hit = 0;
disable();
movedata(FP_SEG(our_interrupt_table), FP_OFF(our_interrupt_table), 0, 0, 256*4);
enable();
page_in_everything();
break;
case 8: /* _setmode() */
_BX=(int)p1;
_AX=0x4400;
geninterrupt(0x21);
i = _DX;
if (p2 & O_BINARY)
i |= 0x20;
else
i &= ~0x20;
_BX=(int)p1;
_DX = i;
_AX=0x4401;
geninterrupt(0x21);
r = setmode((int)p1, (int)p2);
break;
case 9: /* chmod */
retrieve_string(p1+ARENA, buf, 0);
r = chmod(buf, (int)p2);
break;
case 10: /* DPMI exec */
dpmisim_is_exec = 1;
tss_ptr->tss_eax = 0x0300;
i_31();
dpmisim_is_exec = 0;
return 0;
default:
return 1;
}
tss_ptr->tss_eflags &= ~1;
if (r == -1)
{
tss_ptr->tss_eflags |= 1;
tss_ptr->tss_eax = (errno == 35) ? 36 : errno;
return 0;
}
tss_ptr->tss_eax = r;
return 0;
}
i_21_44(void)
{
switch ((word8)(tss_ptr->tss_eax))
{
case 0x00:
case 0x01:
case 0x06:
case 0x07:
case 0x08:
case 0x09:
case 0x0a:
case 0x0b:
case 0x0e:
case 0x0f:
intr(0x21, &r);
tss_ptr->tss_edx = r.r_dx;
tss_ptr->tss_eax = r.r_ax;
tss_ptr->tss_eflags = flmerge(r.r_flags, tss_ptr->tss_eflags);
return 0;
default:
return 1;
}
}